package withouther.system.core.aop.aspectj;


import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.Operation;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import withouther.system.core.constant.LogType;
import withouther.system.core.security.entity.UserInfo;
import withouther.system.core.util.RequestHolder;
import withouther.system.plugins.monitor.service.LogService;

import java.io.PrintWriter;
import java.io.StringWriter;

/**
 * 操作日志记录处理
 *
 * @author tzq
 */
@Aspect
@Component
@Slf4j
public class LogAspect {
    @Autowired
    private LogService logService;

    ThreadLocal<Long> currentTime = new ThreadLocal<>();

    // 配置织入点
    @Pointcut("@annotation(withouther.system.core.aop.log.Log)")
    public void logPointCut(){}


//    @AutoConfigureBefore(pointcut = "logPointCut()")
    @Before("logPointCut()")
    public void doBefore(JoinPoint JoinPoint) throws Throwable{
        currentTime.set(System.currentTimeMillis());
    }

    /**
     * 前置通知 用于拦截操作
     *
     * @param joinPoint 切点
     */
    @AfterReturning(pointcut = "logPointCut()")
    public void doAfterReturning(JoinPoint joinPoint)
    {
        handleLog(joinPoint, null);
    }

    /**
     * 拦截异常操作
     *
     * @param joinPoint
     * @param e
     */
    @AfterThrowing(value = "logPointCut()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Exception e)
    {
        handleLog(joinPoint, e);
    }

    protected void handleLog(final JoinPoint joinPoint, final Exception e)
    {
        try
        {
            withouther.system.plugins.monitor.entity.Log sysLog = new withouther.system.plugins.monitor.entity.Log();
            // 获取当前的用户
            //SysUser currentUser = ShiroUtils.getUser();

            // *========数据库日志=========*//
            sysLog.setUsername(getUsername());
            sysLog.setLogType(LogType.INFO);
            sysLog.setTime(System.currentTimeMillis() - currentTime.get());
            currentTime.remove();
            if (e != null)
            {
                sysLog.setLogType(LogType.ERROR);
                sysLog.setExceptionDetail(getExceptionToString(e));
            }
            logService.save(RequestHolder.getHttpServletRequest(), joinPoint, sysLog);
        }
        catch (Exception exp)
        {
            // 记录本地异常日志
            log.error("==LogAspect异常==");
            log.error("异常信息:{}", exp.getMessage());
            exp.printStackTrace();
        }
    }
    public String getUsername() {
        try {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            UserInfo userInfo = (UserInfo)authentication.getPrincipal();
            return userInfo.getUsername();
        }catch (Exception e){
            return "";
        }
    }
    /**
     * 将 Exception 转化为 String
     */
    public static String getExceptionToString(Throwable e) {
        if (e == null){
            return "";
        }
        StringWriter stringWriter = new StringWriter();
        e.printStackTrace(new PrintWriter(stringWriter));
        return stringWriter.toString();
    }
}
